#pragma once
#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"

using namespace SocketModule;
using namespace LogModule;

class Request{
public:
    Request() {}
    Request(int x, int y, char oper) :_x(x), _y(y), _oper(oper){}

    std::string Serializer(){
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);

        return s;
    }

    bool Deserializer(const std::string& in){
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if(ok){
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }

        return ok;
    }

    int X(){
        return _x;
    }

    int Y(){
        return _y;
    }

    char Oper(){
        return _oper;
    }

    ~Request(){}

private:
    int _x;
    int _y;
    char _oper;
};

class Response{
public:
    Response() {}
    Response(int result, int code) : _result(result), _code(code) {}

    std::string Serializer(){
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }

    bool Deserializer(const std::string& in){
        Json::Value root;
        Json::Reader reader;

        bool ok = reader.parse(in, root);
        if(ok){
            _result = root["result"].asInt();
            _code =  root["code"].asInt();
        }
        return ok;
    }

    void SetResult(int res){
        _result = res;
    }

    void SetCode(int code){
        _code = code;
    }

    void ShowResult(){
        std::cout << "计算结果: " << _result << "[" << _code << "]" << std::endl;
    }

    ~Response(){}

private:
    int _result;
    int _code;
};

using func_t = std::function<Response(Request& req)>;
const std::string& sep = "\r\n";

class Protocol{
public:
    Protocol(){}
    Protocol(func_t func) : _func(func) {}

    std::string Encode(const std::string& jsonstr){
        std::string size_str = std::to_string(jsonstr.size());
        return size_str + sep + jsonstr + sep;
    }

    bool Decode(std::string& buffer, std::string* package){
        int pos = buffer.find(sep);
        if(pos == std::string::npos)
            return false;
        LOG(LogLevel::DEBUG) << "通过Decode第一阶段: 找到pos";
        std::string package_size_str = buffer.substr(0, pos);
        int package_size_int = std::stoi(package_size_str);
        int target_len = package_size_int + package_size_str.size() + 2 * sep.size();
        if(buffer.size() < target_len)
            return false;
        LOG(LogLevel::DEBUG) << "通过Decode第二阶段: 长度符合";
        *package = buffer.substr(pos + sep.size(), package_size_int);
        buffer.erase(0, target_len);
        LOG(LogLevel::DEBUG) << "完全通过Decode";
        return true;
    }

    void GetRequest(std::shared_ptr<Socket>& sock, InetAddr& client){
        std::string buffer_queue;
        while(true){
            int n = sock->Recv(&buffer_queue);
            if(n > 0){
                LOG(LogLevel::DEBUG) << "得到客户端发来的数字串" << buffer_queue;
                std::string json_str;
                while(Decode(buffer_queue, &json_str)){
                    LOG(LogLevel::DEBUG) << client.StringAddr() << "计算：" << json_str;
                    Request req;
                    req.Deserializer(json_str);
                    Response resp = _func(req);

                    std::string resp_str = resp.Serializer();
                    std::string send_str = Encode(resp_str); 

                    sock->Send(send_str);
                }
            }
            else if(n == 0){
                LOG(LogLevel::INFO) << client.StringAddr() << "Quit!";
                break;
            }
            else{
                LOG(LogLevel::ERROR) << "Recv error!";
                break;
            }
        }        
    }

    bool GetResponse(std::shared_ptr<Socket>& sock, std::string& resp_buff, Response* resp){
        while(true){
            int n = sock->Recv(&resp_buff);
            if(n > 0){
                std::string jsonstr;
                while(Decode(resp_buff, &jsonstr)){
                    resp->Deserializer(jsonstr);
                }
                return true;
            }
            else if(n == 0){
                std::cout << "Server Quit!";
                return false;
            }
            else{
                std::cout << "Recv Error!";
                return false;
            }
        }
    }   

    std::string BuildRequestString(int x, int y, char oper){
        Request req(x, y, oper);
        return Encode(req.Serializer());
    }

    
    ~Protocol(){}
private:
    func_t _func;
};